#include <QtGui/QApplication>
#include "ndefmanager.h"

// If 0, all tags detected. Otherwise only the ones passing the filter
#define FILTER_BASED_DETECTION 0

NdefManager::NdefManager(QObject *parent) :
    QObject(parent)
{
    // NdefManager (this) is the parent; will automatically delete nfcManager
    nfcManager = new QNearFieldManager(this);
    nfcManager->setTargetAccessModes(QNearFieldManager::NdefReadTargetAccess | QNearFieldManager::NdefWriteTargetAccess);

#if FILTER_BASED_DETECTION
    // React only to Uri records (NfcRtd, "U")
    QNdefFilter filter;
    filter.appendRecord(QNdefRecord::NfcRtd, "U",0, 1);
    // filter.appendRecord(QNdefRecord::Empty, "",0, 1);
    // filter.appendRecord(QNdefRecord::NfcRtd, "T",0, 1);
    nfcManager->registerNdefMessageHandler(filter,this, SLOT(targetDetected(QNdefMessage,QNearFieldTarget*)));

#else
    connect(nfcManager, SIGNAL(targetDetected(QNearFieldTarget*)), this, SLOT(targetDetected(QNearFieldTarget*)));
    nfcManager->startTargetDetection();
#endif

    // Get notified when the tag gets out of range
    connect(nfcManager, SIGNAL(targetLost(QNearFieldTarget*)),
            this, SLOT(targetLost(QNearFieldTarget*)));
}

NdefManager::~NdefManager()
{
}

void NdefManager::targetDetected(QNearFieldTarget *target)
{
    const bool hasNdefMessage = target->hasNdefMessage();
    if (hasNdefMessage) {
        connect(target, SIGNAL(ndefMessageRead(QNdefMessage)), this, SLOT(ndefMessageRead(QNdefMessage)));
        target->readNdefMessages();
    }

    // Cache target to member variable for writing
    cachedTarget = target;
    connect(cachedTarget, SIGNAL(ndefMessagesWritten()), this, SLOT(writeSucceed()));
    connect(cachedTarget, SIGNAL(error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId & id)), this, SLOT(writeFailed()));
}

void NdefManager::ndefMessageRead(const QNdefMessage &message)
{
    // Go through all records in the message
    foreach (const QNdefRecord &record, message) {
        // Check type again, just to make sure
        if (record.isRecordType<QNdefNfcUriRecord>()) {
            // Convert to the specialized URI record class
            QNdefNfcUriRecord uriRecord(record);
            // Emit a signal with the URI
            emit nfcReadTagUri(uriRecord.uri());
        }
        else if (record.isRecordType<QNdefNfcTextRecord>()) {
            QNdefNfcTextRecord textRecord(record);
            emit nfcReadTagText(textRecord.text());
        }
    }
}

void NdefManager::targetLost(QtMobility::QNearFieldTarget *target)
{
    cachedTarget = NULL;
    target->deleteLater();
}

void NdefManager::nfcWriteUriTag(const QString &nfcTagText) {
    // The device currently has a target in reach
    if (cachedTarget) {
        // Convert text to a URI, adding missing http:// if necessary
        QUrl convertedUrl = QUrl::fromUserInput(nfcTagText);
        // Check if it is a valid URL
        if (convertedUrl.isValid() && nfcTagText.contains('.')) {
            QNdefMessage message;
            // Create a URI NDEF record
            QNdefNfcUriRecord uriRecord;
            uriRecord.setUri(convertedUrl);
            message.append(uriRecord);
            qDebug() << "Writing URI ...";
            // Write NDEF message to the tag
            cachedTarget->writeNdefMessages(QList<QNdefMessage>() << message);
        } else {
            qDebug() << "No valid URI";
        }
    } else {
        qDebug() << "No cached target available";
    }
}

void NdefManager::nfcWriteTextTag(const QString &nfcTagText) {
    // The device currently has a target in reach
    if (cachedTarget) {
        QNdefMessage message;
        // Create a TEXT NDEF record
        QNdefNfcTextRecord textRecord;
        textRecord.setText(nfcTagText);
        message.append(textRecord);
        cachedTarget->writeNdefMessages(QList<QNdefMessage>() << message);
    }
    else {
        qDebug() << "No cached target available";
    }
}

void NdefManager::targetDetected(const QNdefMessage &message, QNearFieldTarget *target)
{
    foreach (const QNdefRecord &record, message) {
        // Check type again, just to make sure
        if (record.isRecordType<QNdefNfcUriRecord>()) {
            // Convert to the specialized URI record class
            QNdefNfcUriRecord uriRecord(record);
            // Emit a signal with the URI
            emit nfcReadTagUri(uriRecord.uri());
        }
        else if (record.isRecordType<QNdefNfcTextRecord>()) {
            QNdefNfcTextRecord textRecord(record);
            emit nfcReadTagText(textRecord.text());
        }
    }
}

void NdefManager::writeFailed()
{
    emit nfcWriteResult(false);
}

void NdefManager::writeSucceed()
{
    emit nfcWriteResult(true);
}
